## [Как в С возвратить массив из функции?](https://ru.stackoverflow.com/questions/946016/Как-в-С-возвратить-массив-из-функции)

Есть функция, которая банально проверяет являеться ли число бинарным

char* bool_input(void){
  char u_inpt[10]="";
  char result[10]="0";
  scanf("%s",u_inpt);

  for (int i = 0; i < strlen(u_inpt); i++) {
    char num = *(u_inpt+i);

    if (num!=*("1")&&num!=*("0")) {
      printf("Error\n");
      bool_input();

    }
    // strcpy(u_inpt, result);
    return result;
  }
}
но она не работает так как возвращаемый объект не char* как вернуть ? P.S искренне прошу прощение если вопрос детский на с я сегодня начал писать



Если на минутку исключить из рассмотрения трюк с заворачиванием массива в struct, то в языке С невозможно буквально вернуть массив из функции (или передать массив в функцию). Массивы в С являются некопируемыми объектами - их нельзя никуда "передать" и ниоткуда "вернуть". Передавать или возвращать вы можете только указатели на массивы (на сами массивы или на их элементы).

По этой причине когда говорят о "возвращении массива из функции" в контексте языка С обычно понимают следующие варианты:

Возвращение указателя на массив (на начало массива). Возвращаемый указатель не может указывать на автоматический массив, объявленный внутри этой функции, так как такой массив будет уничтожен при выходе из функции.

Возвращаемый указатель может указывать на динамически выделенную память

char *bool_input(void)
{
  char *result = malloc(/* размер */);

  /* Заполнение массива */

  return result;
}
В таком случае освобождение выделенной памяти - обязанность вызывающего кода.

Либо он может указывать на массив со статическим временем жизни

char *bool_input(void)
{
  static char result[/* размер */];

  /* Заполнение массива */

  return result;
}
Большим недостатком такого варианта является то, что он нереентерабелен, но и у него (в различных вариациях) есть свои применения.

Массив передается в функцию снаружи и о его создании и удалении заботится именно вызывающий код. А функция занимается лишь заполнением массива

void bool_input(char result[], size_t size)
{
  /* Заполнение массива */
}
Если вам так больше нравится, вы можете сделать и так

char *bool_input(char result[], size_t size)
{
  /* Заполнение массива */

  return result;
}
Ну и в качестве побочного варианта можно вспомнить об упоминавшемся выше варианте с заворачиванием массива в структуру. Такой вариант применяется редко и как правило имеет смысл лишь для массивов небольшого размера, которые всегда используются целиком

struct Point
{
  int xyz[3];
}; 

struct Point point_123(void)
{
  return (struct Point) { { 1, 2, 3 } };
}
Основным вариантом "возвращения массивов" в языке С является именно вариант номер 2. А вариант 1 при желании можно реализовать в виде надстройки над вариантом 2.

Поделиться
Улучшить ответ
Отслеживать
изменён 23 фев 2019 в 19:10
ответ дан 23 фев 2019 в 17:30
user avatar
AnT stands with Russia
67.9k33 золотых знака5757 серебряных знаков134134 бронзовых знака
Добавить комментарий

2

Всё дело в том, как вы создаете result.

В языке си при вызове функции в стеке (вызовов) выделяется память под локальные переменные, то есть аргументы и переменные указанные в начале функции. При этом, например, char arr[100] выделит 100 байт, char * arr = malloc (100) выделит только sizeof (char *) байт (то есть размер указателя). При этом при выходе из функции все такие объекты уничтожаются. Не уничтожаются те объекты, память под которые была выделена в куче (например, функцией malloc).

Стало быть, Вам стоит выделять память под result с помощью команды malloc (из stdlib.h) и не забыть потом её освободить с помощью функции free в том месте, где result Вам более не нужен. Например:

#include <stdlib.h>

char * f (void) {    
    char * result = malloc (n);
    // Проверка
    if (result == NULL) { return NULL; }
    // ...
    return result;
}

int main (void) {
    char * result;
    // ...
    result = f ();
    // ...
    free (result);
    // ...
    return 0;
}